package transport

import (
	"io"
	"rpc-go/server/config"
	"rpc-go/utils"
	"strings"
	"bufio"
	"strconv"
	"fmt"
	"time"
)

// 聚美定义的rpc text协议，格式是
// commandLent
type JumeiTextRPC struct {
	Command string
	Data    string
}

//// 一直监听并读取连接中的数据
//func ReceiveClientData(jmConn *JumeiConn, dataChan chan *JumeiTextRPC) (err error) {
//	defer utils.PrintPanicStack()
//	var dataBox []byte
//	var size int
//	for {
//		readData := make([]byte, 1024)
//		size, err = jmConn.Conn.Read(readData)
//		if err != nil {
//			if err != io.EOF {
//				config.Logger.Error("not eof error:", err.Error())
//			} else {
//				config.Logger.Errorf("client %s closed ", jmConn.Conn.RemoteAddr())
//			}
//			// dataBox = dataBox[0:0]
//			dataBox = nil
//			readData = nil
//			return
//		}
//		dataBox = append(dataBox, readData[0:size]...)
//		readData = nil
//		//读完后，进行解包
//	dealdata:
//		dataString := string(dataBox)
//		sepNumber := strings.Count(dataString, "\n")
//		if sepNumber >= 4 {
//
//			command, data, leftstring, unWrapErr := codec.UnWrapC2SData(dataString)
//			if unWrapErr != nil {
//				// 如果解包出现问题，说明数据已经乱了。则丢掉之前的数据
//				config.Logger.Errorf("decode %s ,and error %s", dataString, unWrapErr.Error())
//				dataBox = dataBox[0:0]
//				continue
//			}
//			dataChan <- &JumeiTextRPC{Command: command, Data: data}
//			dataBox = dataBox[0:0]
//			// 如果还有剩余数据，那么继续处理
//			if len(leftstring) > 0 {
//				dataBox = []byte(leftstring)
//				leftstring = ""
//				goto dealdata
//			}
//			return
//		}
//
//	}
//
//}


// 一直监听并读取连接中的数据
func ReceiveClientData(jmConn *JumeiConn, dataChan chan *JumeiTextRPC, stopChan chan bool) {
	defer utils.PrintPanicStack()

	buf := bufio.NewReader(jmConn.Conn)


	//超时时间2秒
	go HeartBeating(jmConn, stopChan,true, 2)


	_, _, err := buf.ReadLine()
	if err != nil {
		if err == io.EOF {
			close(stopChan)
			return
		}
		config.Logger.Error("read error:", err.Error())
		return
	}


	//cmd
	command, _, err := buf.ReadLine()
	if err != nil {
		config.Logger.Error("read error:", err.Error())
		return
	}

	//bodyLen
	bodyTag, _, err := buf.ReadLine()
	if err != nil {
		config.Logger.Error("read error: ", err.Error())
		return
	}

	bodyLen, err := strconv.Atoi(strings.Trim(string(bodyTag), "\000"))
	if err != nil {
		config.Logger.Error("strconv error: ", err.Error())
		return
	}

	//body
	reqData := make([]byte, bodyLen)
	start, count := 0, 0
	for {
		if start == bodyLen {
			break
		}
		count, err = buf.Read(reqData[start:])
		if err == nil {
			start += count
		} else {
			config.Logger.Error("read error: ", err.Error())
			break
		}
	}

	dataChan <- &JumeiTextRPC{Command: string(command), Data: string(reqData)}
}

func HeartBeating(conn *JumeiConn, stopChan chan bool, ready bool, timeout int) {
	select {
	case ready:
		conn.Conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
	case <-time.After(time.Second * 10):
		conn.SendError("client request data read timeout.", false)
		conn.Conn.Close()
		close(stopChan)
	}
}

